package com.ansion.commonchat.startup.workmanager.bwork.impl.background.greedy;

import android.content.Context;

import androidx.annotation.NonNull;

import com.ansion.commonchat.startup.workmanager.bwork.BWorkInfo;
import com.ansion.commonchat.startup.workmanager.bwork.impl.BScheduler;
import com.ansion.commonchat.startup.workmanager.bwork.impl.BWorkManagerImpl;
import com.ansion.commonchat.startup.workmanager.bwork.impl.mode.BWorkSpec;
import com.ansion.log.LogTag;
import com.ansion.log.VLog;


/**
 * Created by wanghongjie on 2023/5/6
 * Describe : WorkManager 框架中负责根据贪婪调度策略调度工作，以提高工作执行的效率和并发性，并根据执行环境的变化进行动态调整
 * <p>
 * 1.尽快运行可运行的工作：它会优先选择已准备好且满足约束条件的工作，以尽快执行它们。
 * 2.最大化并发执行：它会尝试在合适的情况下同时调度多个工作，以最大程度地利用设备的处理能力。
 * 3.动态调整调度策略：它会根据工作的状态和设备资源的可用性进行动态调整，以适应不同的执行环境。
 */
public class BGreedyScheduler implements BScheduler {

    private final Context mContext;
    private final BWorkManagerImpl mWorkManagerImpl;

    public BGreedyScheduler(
            @NonNull Context context,
            @NonNull BWorkManagerImpl workManagerImpl) {
        mContext = context;
        mWorkManagerImpl = workManagerImpl;
    }

    @Override
    public boolean hasLimitedSchedulingSlots() {
        return false;
    }

    @Override
    public void schedule(@NonNull BWorkSpec... workSpecs) {
        for (BWorkSpec workSpec : workSpecs) {
            /**
             * 开始调度任务 -> BSerialExecutor 加入队列，实现顺序调度 ->
             * -> BStartWorkRunnable 获取 BProcessor StartWork  -> BProcessor startWork 转换 BWorkerWrapper 加入队列 ->
             * -> BWorkerWrapper 具体实现 StartWork , onWorkFinished 调度下一个任务
             */
            if (workSpec.state == BWorkInfo.State.ENQUEUED) {
                if (VLog.OPEN_LOG)
                    VLog.d(LogTag.TAG_B_WORK_MANAGER, "Starting work for %s", workSpec.id);
                mWorkManagerImpl.startWork(workSpec.id);
            }
        }
    }

    @Override
    public void cancel(@NonNull String workSpecId) {
        if (VLog.OPEN_LOG)
            VLog.d(LogTag.TAG_B_WORK_MANAGER, "Cancelling work ID %s", workSpecId);
        mWorkManagerImpl.stopWork(workSpecId);
    }
}